
#ifndef _SHARED_FD_H_20180923_
#define _SHARED_FD_H_20180923_

#include "smart_fd_inner.hpp"

namespace SmartFd {

SharedFd::SharedFd()
    : detail_(NULL)
{ }

SharedFd::SharedFd(int fd)
    : detail_(new SmartFd::SharedDetail(fd))
{
    detail_->sharedRef();
}

SharedFd::SharedFd(int fd, SmartFd::Deleter del)
    : detail_(new SmartFd::SharedDetail(fd, del))
{
    detail_->sharedRef();
}

SharedFd::SharedFd(const SharedFd &other)
{
    detail_ = other.detail_;
    if (detail_ != NULL)
        detail_->sharedRef();
}

SharedFd::SharedFd(const WeakFd &other)
{
    detail_ = other.detail_;
    if (detail_ != NULL)
        detail_->sharedRef();
}

SharedFd::~SharedFd()
{
    if (detail_ != NULL) {
        detail_->sharedUnref();
        if (!detail_->anyRef()) {
            delete detail_;
        }
    }
}

void SharedFd::swap(SharedFd &other)
{
    if (this == &other)
        return;

    std::swap(detail_, other.detail_);
}

void SharedFd::reset()
{
    SharedFd().swap(*this);
}

SharedFd& SharedFd::operator = (const SharedFd &other)
{
    if (this == &other)
        return *this;

    reset();

    detail_ = other.detail_;
    if (detail_ != NULL)
        detail_->sharedRef();

    return *this;
}

SharedFd& SharedFd::operator = (const WeakFd &other)
{
    reset();

    if (other.empty())
        return *this;

    detail_ = other.detail_;
    if (detail_ != NULL)
        detail_->sharedRef();

    return *this;
}

bool SharedFd::empty() const
{
    return detail_ == NULL;
}

SharedFd::operator int () const
{
    if (detail_ != NULL)
        return detail_->getFd();

    return -1;
}

bool SharedFd::owner_before(const SharedFd &other) const
{
    return detail_ < other.detail_;
}

bool SharedFd::owner_after(const SharedFd &other) const
{
    return detail_ > other.detail_;
}

inline bool operator < (const SharedFd &lhs, const SharedFd &rhs) {
    return lhs.owner_before(rhs);
}

inline bool operator > (const SharedFd &lhs, const SharedFd &rhs) {
    return lhs.owner_after(rhs);
}

inline bool operator == (const SharedFd &lhs, const SharedFd &rhs) {
    return !lhs.owner_before(rhs) && !lhs.owner_after(rhs);
}

inline bool operator != (const SharedFd &lhs, const SharedFd &rhs) {
    return lhs.owner_before(rhs) || lhs.owner_after(rhs);
}

inline void swap(SharedFd &lhs, SharedFd &rhs) {
    lhs.swap(rhs);
}

}

typedef SmartFd::SharedFd SharedFd;

#endif //_SHARED_FD_H_20180923_
